/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.ui.toolbar; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.InlineLabel; import com.google.inject.Provider; import org.eclipse.che.ide.api.action.Action; import org.eclipse.che.ide.api.action.ActionGroup; import org.eclipse.che.ide.api.action.ActionManager; import org.eclipse.che.ide.api.action.ActionSelectedHandler; import org.eclipse.che.ide.api.action.Presentation; import org.eclipse.che.ide.api.action.PropertyChangeEvent; import org.eclipse.che.ide.api.action.PropertyChangeListener; import org.eclipse.che.ide.api.keybinding.KeyBindingAgent; import org.eclipse.che.ide.api.parts.PerspectiveManager; import org.eclipse.che.ide.ui.Tooltip; import org.eclipse.che.ide.ui.menu.PositionController; import org.vectomatic.dom.svg.ui.SVGImage; /** * @author Evgen Vidolob * @author Dmitry Shnurenko */ public class ActionPopupButton extends Composite implements CloseMenuHandler, ActionSelectedHandler { private final ActionGroup action; private final ActionManager actionManager; private final Provider<PerspectiveManager> managerProvider; private final Presentation presentation; private ActionButtonSynchronizer actionButtonSynchronizer; private KeyBindingAgent keyBindingAgent; private PresentationFactory presentationFactory; private ToolbarResources toolbarResources; /** Enabled state. True as default. */ private boolean enabled = true; /** Lock Layer uses for locking rest of the screen, which does not covered by Popup Menu. */ private MenuLockLayer lockLayer; /** Popup Menu button panel (<div> HTML element). */ private ButtonPanel panel; /** Has instance if Popup Menu is opened. */ private PopupMenu popupMenu; /** Tooltip */ private Tooltip tooltip; /** Create Popup Menu Button with specified icons for enabled and disabled states. */ public ActionPopupButton(final ActionGroup action, ActionManager actionManager, KeyBindingAgent keyBindingAgent, final PresentationFactory presentationFactory, Provider<PerspectiveManager> managerProvider, ToolbarResources toolbarResources) { this.action = action; this.actionManager = actionManager; this.keyBindingAgent = keyBindingAgent; this.presentationFactory = presentationFactory; this.managerProvider = managerProvider; this.toolbarResources = toolbarResources; presentation = presentationFactory.getPresentation(action); panel = new ButtonPanel(); initWidget(panel); panel.setStyleName(toolbarResources.toolbar().popupButtonPanel()); renderImage(); setEnabled(presentation.isEnabled()); setVisible(presentation.isVisible()); if (presentation.getDescription() != null) { tooltip = Tooltip.create((elemental.dom.Element) panel.getElement(), PositionController.VerticalAlign.BOTTOM, PositionController.HorizontalAlign.MIDDLE, presentation.getDescription()); } this.ensureDebugId("PopupButton/" + action.getTemplatePresentation().getText()); } /** * Redraw the icon. */ private void renderImage() { panel.clear(); if (presentation.getImageResource() != null) { Image image = new Image(presentationFactory.getPresentation(action).getImageResource()); image.setStyleName(toolbarResources.toolbar().popupButtonIcon()); panel.add(image); } else if (presentation.getSVGResource() != null) { SVGImage image = new SVGImage(presentation.getSVGResource()); image.getElement().setAttribute("class", toolbarResources.toolbar().popupButtonIcon()); panel.add(image); } else if (presentation.getHTMLResource() != null) { FlowPanel icon = new FlowPanel(); icon.setStyleName(toolbarResources.toolbar().iconButtonIcon()); FlowPanel inner = new FlowPanel(); inner.setStyleName(toolbarResources.toolbar().popupButtonIconInner()); inner.getElement().setInnerHTML(presentation.getHTMLResource()); icon.add(inner); panel.add(inner); } InlineLabel caret = new InlineLabel(""); caret.setStyleName(toolbarResources.toolbar().caret()); panel.add(caret); } /** {@inheritDoc} */ @Override protected void onLoad() { super.onLoad(); if (actionButtonSynchronizer == null) { actionButtonSynchronizer = new ActionButtonSynchronizer(); presentation.addPropertyChangeListener(actionButtonSynchronizer); } } /** {@inheritDoc} */ @Override protected void onUnload() { super.onUnload(); if (actionButtonSynchronizer != null) { presentation.removePropertyChangeListener(actionButtonSynchronizer); actionButtonSynchronizer = null; } } /** Closes Popup Menu ( if opened ) and sets style of this Popup Menu Button to default. */ protected void closePopupMenu() { if (popupMenu != null) { popupMenu.removeFromParent(); popupMenu = null; } if (lockLayer != null) { lockLayer.removeFromParent(); lockLayer = null; } panel.setStyleName(toolbarResources.toolbar().popupButtonPanel()); } /** * Get is this button enabled. * * @return is enabled */ public boolean isEnabled() { return enabled; } /** * Set is enabled. * * @param enabled * is enabled */ public void setEnabled(boolean enabled) { this.enabled = enabled; if (enabled) { panel.getElement().removeClassName(toolbarResources.toolbar().disabled()); } else { panel.getElement().addClassName(toolbarResources.toolbar().disabled()); } } /** {@inheritDoc} */ public void onCloseMenu() { closePopupMenu(); } /** Mouse Down handler. */ private void onMouseDown() { panel.setStyleName(toolbarResources.toolbar().popupButtonPanelDown()); } /** Mouse Out Handler. */ private void onMouseOut() { if (popupMenu != null) { return; } panel.setStyleName(toolbarResources.toolbar().popupButtonPanel()); } private void onMouseClick() { openPopupMenu(); } /** Mouse Over handler. */ private void onMouseOver() { } /** Opens Popup Menu. */ public void openPopupMenu() { lockLayer = new MenuLockLayer(this); popupMenu = new PopupMenu(action, actionManager, managerProvider, presentationFactory, lockLayer, this, keyBindingAgent, "toolbar"); lockLayer.add(popupMenu); int left = getAbsoluteLeft(); int top = getAbsoluteTop() + 24; popupMenu.getElement().getStyle().setTop(top, com.google.gwt.dom.client.Style.Unit.PX); popupMenu.getElement().getStyle().setLeft(left, com.google.gwt.dom.client.Style.Unit.PX); } /** {@inheritDoc} */ @Override public void onActionSelected(Action action) { closePopupMenu(); } /** This class uses to handling mouse events on Popup Button. */ private class ButtonPanel extends FlowPanel { public ButtonPanel() { sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN | Event.ONMOUSEUP | Event.ONCLICK); } /** Handle browser's events. */ @Override public void onBrowserEvent(Event event) { if (!enabled) { return; } switch (DOM.eventGetType(event)) { case Event.ONMOUSEOVER: onMouseOver(); break; case Event.ONMOUSEOUT: onMouseOut(); break; case Event.ONMOUSEDOWN: if (event.getButton() == Event.BUTTON_LEFT) { onMouseDown(); } break; case Event.ONCLICK: onMouseClick(); break; } } } private class ActionButtonSynchronizer implements PropertyChangeListener { protected static final String SELECTED_PROPERTY_NAME = "selected"; @Override public void onPropertyChange(PropertyChangeEvent e) { String propertyName = e.getPropertyName(); if (Presentation.PROP_TEXT.equals(propertyName)) { if (tooltip != null && e.getNewValue() instanceof String) { tooltip.setTitle((String)e.getNewValue()); } } else if (Presentation.PROP_ENABLED.equals(propertyName)) { setEnabled((Boolean) e.getNewValue()); } else if (Presentation.PROP_ICON.equals(propertyName)) { renderImage(); } else if (Presentation.PROP_VISIBLE.equals(propertyName)) { setVisible((Boolean) e.getNewValue()); } else if (SELECTED_PROPERTY_NAME.equals(propertyName)) { setSelected((Boolean) e.getNewValue()); } } private void setSelected(boolean selected) { if (selected) { panel.setStyleName(toolbarResources.toolbar().iconButtonPanelSelected()); } } } }